package com.talent.core.protocol.mqtt.codec.decoder;

import com.talent.core.protocol.mqtt.model.fix.TlMqttFixedHead;
import com.talent.core.protocol.mqtt.model.payload.TlMqttConnectPayload;
import com.talent.core.protocol.mqtt.model.request.TlMqttConnectReq;
import com.talent.core.protocol.mqtt.model.variable.TlMqttConnectVariableHead;
import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @ClassName：TlConnectDecoder
 * @Author: hszhou
 * @Date: 2024/11/30 15:12
 * @Description: mqtt的连接报文解码器
 */
public class TlMqttConnectDecoder {

    private static final  Logger logger = LoggerFactory.getLogger(TlMqttConnectDecoder.class);


    public TlMqttConnectReq build(ByteBuf buf,int type,int remainingLength){
        TlMqttFixedHead fixedHead = decodeFixedHeader( type, remainingLength);
        TlMqttConnectVariableHead variableHead = decodeVariableHeader(buf);
        TlMqttConnectPayload payload = decodePayLoad(buf,variableHead.getWillFlag(),variableHead.getUsernameFlag(),variableHead.getWillQos());
        return new TlMqttConnectReq(fixedHead,variableHead,payload);

    }


    TlMqttFixedHead decodeFixedHeader(int type,int remainingLength) {
        TlMqttFixedHead fixedHead =new TlMqttFixedHead();
        int messageType = type >> 4;
        fixedHead.setType(type);
        fixedHead.setMessageType(messageType);
        fixedHead.setLength(remainingLength);
        return fixedHead;
    }


    TlMqttConnectVariableHead decodeVariableHeader(ByteBuf buf) {
        TlMqttConnectVariableHead variableHead = new TlMqttConnectVariableHead();
        int protocolLength = buf.readUnsignedShort();
        variableHead.setProtocolNameLength(protocolLength);
        byte[] protocolName = new byte[4];
        buf.readBytes(protocolName);
        short version = buf.readUnsignedByte();
        variableHead.setProtocolVersion(version);
        //连接标识
        int connectFlag = buf.readUnsignedByte();
        int reserved =(connectFlag) &1;
        variableHead.setReserved(reserved);
        int clearSession= (connectFlag>>1)&1;
        variableHead.setCleanSession(clearSession);
        int willFlag= (connectFlag>>2)&1;
        variableHead.setWillFlag(willFlag);
        int willQos= (connectFlag>>3)&3;
        variableHead.setWillQos(willQos);
        int willRetain= (connectFlag>>5)&1;
        variableHead.setWillRetain(willRetain);
        int passwordFlag= (connectFlag>>6)&1;
        variableHead.setPasswordFlag(passwordFlag>0);
        int usernameFlag= (connectFlag>>7)&1;
        variableHead.setUsernameFlag(usernameFlag>0);
        short keepAlive = buf.readShort();
        variableHead.setKeepAlive(keepAlive);
        logger.debug("解析到【CONNECT】消息的可变头 :协议=【{}】版本=【{}】,保留字段=【{}】,会话清除=【{}】," +
                        "遗嘱位=【{}】,遗嘱Qos=【{}】,willRetain=【{}】,用户标记位=【{}】,存活时间=【{}】",
                new String(protocolName),version,reserved,clearSession,
                willFlag,willQos,willRetain,usernameFlag,keepAlive);
        return variableHead;
    }

    TlMqttConnectPayload decodePayLoad(ByteBuf buf,int willFlag,boolean usernameFlag,int willQOs) {
        int clientIdLength = buf.readUnsignedShort();
        byte[] clientIdByte =new byte[clientIdLength];
        buf.readBytes(clientIdByte);
        String clientId = new String(clientIdByte);
        TlMqttConnectPayload connectPayload = new TlMqttConnectPayload();
        connectPayload.setClientId(clientId);
        String willTopic = "";
        String willMessage = "";
        String username="";
        String password="";
        if(willFlag==1){
            int willTopicLength = buf.readUnsignedShort();
            byte[] willTopicByte =new byte[willTopicLength];
            buf.readBytes(willTopicByte);
             willTopic = new String(willTopicByte);
            connectPayload.setWillTopic(willTopic);

            int messageLength = buf.readUnsignedShort();
            byte[] messageByte =new byte[messageLength];
            buf.readBytes(messageByte);
            willMessage = new String(messageByte);
            connectPayload.setWillMessage(willMessage);
      }

        if (usernameFlag){
            int usernameLength = buf.readUnsignedShort();
            byte[] usernameByte =new byte[usernameLength];
            buf.readBytes(usernameByte);
            username = new String(usernameByte);
            connectPayload.setUsername(username);

            int passwordLength = buf.readUnsignedShort();
            byte[] passwordByte =new byte[passwordLength];
            buf.readBytes(passwordByte);
            password = new String(passwordByte);
            connectPayload.setPassword(password);
        }
        logger.debug("解析【CONNECT】的payload的clientId=【{}】,willFlag=【{}】,willTopic=【{}】，retain=【{}】，username=【{}】",
                clientId,willFlag,willQOs,willTopic,username);
        return connectPayload;
    }
}
